import logging

from fastapi import FastAPI, HTTPException, applications
from fastapi.exceptions import RequestValidationError
from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html
from pydantic import ValidationError
from redis import RedisError

from app.api.routers.auth_router import router as auth_router
from app.api.routers.dept_router import router as dept_router
from app.api.routers.dict_router import router as dict_router
from app.api.routers.log_router import router as log_router
from app.api.routers.menu_router import router as menu_router
from app.api.routers.notice_router import router as notice_router
from app.api.routers.role_router import router as role_router
from app.api.routers.user_router import router as user_router

# from app.api.routers.websocket_router import router as websocket_router
from app.exceptions.base import AppException
from app.exceptions.handlers import (
    app_exception_handler,
    global_exception_handler,
    http_exception_handler,
    invalid_refresh_token_handler,
    invalid_token_handler,
    redis_rrror_handler,
    type_error_handler,
    unicode_encode_error_handler,
    user_account_frozen_handler,
    user_duplicate_handler,
    user_not_found_handler,
    validation_exception_handler,
)
from app.exceptions.user import (
    InvalidRefreshTokenException,
    InvalidTokenException,
    UserAccountFrozenException,
    UserDuplicateException,
    UserNotFoundException,
)

# 获取日志记录器
logger = logging.getLogger(__name__)


def include_router_handle(app: FastAPI) -> None:
    """
    注册路由

    :param app: FastAPI 应用实例
    """
    # 示例路由注册
    app.include_router(router=auth_router)
    app.include_router(router=user_router)
    app.include_router(router=role_router)
    app.include_router(router=menu_router)
    app.include_router(router=dept_router)
    app.include_router(router=dict_router)
    app.include_router(router=log_router)
    app.include_router(router=notice_router)
    # app.include_router(router=websocket_router)


def register_exceptions(app: FastAPI):
    """统一异常

    Args:
        app (FastAPI): _description_
    """
    app.add_exception_handler(HTTPException, http_exception_handler)
    app.add_exception_handler(TypeError, type_error_handler)
    app.add_exception_handler(RequestValidationError, validation_exception_handler)
    app.add_exception_handler(ValidationError, validation_exception_handler)
    app.add_exception_handler(UserNotFoundException, user_not_found_handler)
    app.add_exception_handler(UserAccountFrozenException, user_account_frozen_handler)
    app.add_exception_handler(InvalidTokenException, invalid_token_handler)
    app.add_exception_handler(InvalidRefreshTokenException, invalid_refresh_token_handler)
    app.add_exception_handler(UserDuplicateException, user_duplicate_handler)
    app.add_exception_handler(RedisError, redis_rrror_handler)
    app.add_exception_handler(AppException, app_exception_handler)
    app.add_exception_handler(Exception, global_exception_handler)
    app.add_exception_handler(UnicodeEncodeError, unicode_encode_error_handler)


def reset_api_docs(swagger_ui_version: str = "5", redoc_version: str = "next") -> None:
    """
    修复 Swagger UI 和 ReDoc API 文档 CDN 无法访问的问题

    通过猴子补丁的方式替换 FastAPI 默认的文档 CDN 链接，
    使用 unpkg.com 的 CDN 来提供更好的访问体验。

    :param swagger_ui_version: Swagger UI 版本号，默认为 "5"
    :param redoc_version: ReDoc 版本号，默认为 "next"

    Example:
        # 在应用启动时调用
        reset_api_docs()

        # 或者指定特定版本
        reset_api_docs(swagger_ui_version="4", redoc_version="latest")
    """
    # 构建 Swagger UI CDN URLs
    swagger_css_url = f"https://unpkg.com/swagger-ui-dist@{swagger_ui_version}/swagger-ui.css"
    swagger_js_url = f"https://unpkg.com/swagger-ui-dist@{swagger_ui_version}/swagger-ui-bundle.js"

    # 构建 ReDoc CDN URL
    redoc_js_url = f"https://unpkg.com/redoc@{redoc_version}/bundles/redoc.standalone.js"

    def swagger_monkey_patch(*args, **kwargs):
        """
        Swagger UI 猴子补丁函数

        替换默认的 Swagger UI CDN 链接
        """
        logger.debug(f"Using Swagger UI CSS: {swagger_css_url}")
        logger.debug(f"Using Swagger UI JS: {swagger_js_url}")

        return get_swagger_ui_html(
            *args,
            **kwargs,
            swagger_css_url=swagger_css_url,
            swagger_js_url=swagger_js_url,
        )

    def redoc_monkey_patch(*args, **kwargs):
        """
        ReDoc 猴子补丁函数

        替换默认的 ReDoc CDN 链接
        """
        logger.debug(f"Using ReDoc JS: {redoc_js_url}")

        return get_redoc_html(
            *args,
            **kwargs,
            redoc_js_url=redoc_js_url,
        )

    # 应用猴子补丁
    applications.get_swagger_ui_html = swagger_monkey_patch
    applications.get_redoc_html = redoc_monkey_patch

    logger.debug("API docs CDN URLs have been successfully patched")
    logger.debug("API docs CDN URLs have been successfully patched")
